package fr.raskal.musicalflow.repo.impl;

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Repository;

import com.sun.syndication.feed.synd.SyndEntry;
import com.sun.syndication.feed.synd.SyndFeed;
import com.sun.syndication.io.FeedException;
import com.sun.syndication.io.SyndFeedInput;
import com.sun.syndication.io.XmlReader;

import fr.raskal.musicalflow.core.RssDirectory;
import fr.raskal.musicalflow.domain.Feed;
import fr.raskal.musicalflow.domain.Source;
import fr.raskal.musicalflow.domain.Topic;
import fr.raskal.musicalflow.exception.ApplicationException;
import fr.raskal.musicalflow.repo.TopicDao;

@Repository
public class TopicDaoImpl implements TopicDao {

	/**
	 * Logger
	 */
	private static Logger LOGGER = LoggerFactory.getLogger(TopicDaoImpl.class);

	/**
	 * find all topics
	 */
	@Override
	public List<Topic> findAll() throws ApplicationException {

		// top chrono
		Date start = new Date();

		Map<Date, Topic> newsFeed = new TreeMap<Date, Topic>();
		Topic topic = null;

		// process for each feed for each source
		for (Source source : new RssDirectory().getSources()) {

			for (Feed feed : source.getFeeds()) {

				try {
					// create URL
					URL url = new URL(feed.getUrl());

					XmlReader reader = new XmlReader(url);
					SyndFeed syndFeed = new SyndFeedInput().build(reader);

					for (Iterator i = syndFeed.getEntries().iterator(); i.hasNext();) {
						// for each entry
						SyndEntry entry = (SyndEntry) i.next();

						// create a new topic
						topic = new Topic();

						// fill the topic
						topic.setPublishedDate(entry.getPublishedDate());
						topic.setTitle(entry.getTitle());
						topic.setLink(entry.getLink());
						topic.setDescription(entry.getDescription().getValue());
						topic.setSource(source);
						topic.setGenre(feed.getGenre());

						if (LOGGER.isDebugEnabled()) {
							LOGGER.debug(topic.toString());
						}

						// put topic in the map
						newsFeed.put(topic.getPublishedDate(), topic);
					}

				} catch (MalformedURLException e) {
					e.printStackTrace();
					LOGGER.error(e.getLocalizedMessage());
					throw new ApplicationException("There is a problem in the URL");
				} catch (IOException e) {
					e.printStackTrace();
					LOGGER.error(e.getLocalizedMessage());
					throw new ApplicationException("Unable to connect to the URL");
				} catch (IllegalArgumentException e) {
					e.printStackTrace();
					LOGGER.error(e.getLocalizedMessage());
					throw new ApplicationException("There is a problem with SyndFeed");
				} catch (FeedException e) {
					e.printStackTrace();
					LOGGER.error(e.getLocalizedMessage());
					throw new ApplicationException("There is a problem with SyndFeed");
				}
			}

		}

		// stop chrono
		Date end = new Date();

		// returns process duration
		long diff = end.getTime() - start.getTime();
		LOGGER.info(newsFeed.size() + " topics retrieved in " + diff / 1000
				+ "," + diff % 100 + " seconds !");

		return new ArrayList<Topic>(newsFeed.values());
	}

}
